This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

1'use client'; 2 3import { useEffect, useState } from 'react'; 4import { useRouter, useParams } from 'next/navigation'; 5import { getAccessToken } from '@/services/auth'; 6import { ApiClient } from '@/api-client/ApiClient'; 7import { UrlCard } from '@/components/UrlCard'; 8import type { GetCollectionPageResponse } from '@/api-client/types'; 9import { 10 Button, 11 Group, 12 Loader, 13 Stack, 14 Text, 15 Card, 16 Title, 17 Box, 18 SimpleGrid, 19} from '@mantine/core'; 20 21export default function CollectionPage() { 22 const [collection, setCollection] = 23 useState<GetCollectionPageResponse | null>(null); 24 const [loading, setLoading] = useState(true); 25 const [error, setError] = useState(''); 26 const router = useRouter(); 27 const params = useParams(); 28 const collectionId = params.collectionId as string; 29 30 // Create API client instance 31 const apiClient = new ApiClient( 32 process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:3000', 33 () => getAccessToken(), 34 ); 35 36 useEffect(() => { 37 const fetchCollection = async () => { 38 try { 39 setLoading(true); 40 const response = await apiClient.getCollectionPage(collectionId, { 41 limit: 50, 42 }); 43 setCollection(response); 44 } catch (error: any) { 45 console.error('Error fetching collection:', error); 46 setError(error.message || 'Failed to load collection'); 47 } finally { 48 setLoading(false); 49 } 50 }; 51 52 if (collectionId) { 53 fetchCollection(); 54 } 55 }, [collectionId]); 56 57 if (loading) { 58 return <Loader />; 59 } 60 61 if (error || !collection) { 62 return ( 63 <Stack align="center"> 64 <Text c={'red'}>{error || 'Collection not found'}</Text> 65 <Button onClick={() => router.back()}>Go Back</Button> 66 </Stack> 67 ); 68 } 69 70 return ( 71 <Box> 72 <Stack> 73 <Group justify="space-between"> 74 <Button variant="outline" onClick={() => router.back()}> 75 Back 76 </Button> 77 <Group> 78 <Button 79 variant="outline" 80 onClick={() => router.push(`/collections/${collectionId}/edit`)} 81 > 82 Edit Collection 83 </Button> 84 <Button 85 onClick={() => 86 router.push(`/cards/add?collectionId=${collectionId}`) 87 } 88 > 89 Add Card 90 </Button> 91 </Group> 92 </Group> 93 94 {/* Collection Header */} 95 <Card withBorder> 96 <Stack> 97 <Text fw={600} lineClamp={1}> 98 {collection.name} 99 </Text> 100 {collection.description && ( 101 <Text lineClamp={2}>{collection.description}</Text> 102 )} 103 </Stack> 104 105 <Group> 106 <Text fz={'sm'} c={'gray'}> 107 {collection.urlCards.length} cards 108 </Text> 109 <Text fz={'sm'} c={'gray'}> 110 By {collection.author.name} (@{collection.author.handle}) 111 </Text> 112 </Group> 113 </Card> 114 115 {/* Cards Section */} 116 <Stack> 117 <Group justify="space-between"> 118 <Title order={2}>Cards</Title> 119 {collection.pagination && collection.pagination.totalCount > 0 && ( 120 <Text fz={'sm'} c={'gray'}> 121 Showing {collection.urlCards.length} of{' '} 122 {collection.pagination.totalCount} cards 123 </Text> 124 )} 125 </Group> 126 127 {collection.urlCards.length > 0 ? ( 128 <Box> 129 <SimpleGrid cols={{ base: 1, sm: 2, lg: 3 }} spacing={'md'}> 130 {collection.urlCards.map((card) => ( 131 <UrlCard 132 key={card.id} 133 cardId={card.id} 134 url={card.url} 135 title={card.cardContent.title} 136 description={card.cardContent.description} 137 author={card.cardContent.author} 138 imageUrl={card.cardContent.thumbnailUrl} 139 addedAt={card.createdAt} 140 note={card.note?.text} 141 /> 142 ))} 143 </SimpleGrid> 144 145 {/* Pagination */} 146 {collection.pagination && collection.pagination.hasMore && ( 147 <Stack align="center"> 148 <Button variant="outline">Load More Cards</Button> 149 </Stack> 150 )} 151 </Box> 152 ) : ( 153 <Stack align="center"> 154 <Text c={'gray'}>No cards in this collection yet</Text> 155 <Button 156 onClick={() => 157 router.push(`/cards/add?collectionId=${collectionId}`) 158 } 159 > 160 Add Your First Card 161 </Button> 162 </Stack> 163 )} 164 </Stack> 165 </Stack> 166 </Box> 167 ); 168}